package math2.delaunay;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

public class Delaunay2 extends AbstractDelaunay {
	private Point[] bps;
	private List<Point> points;
	private Set<Triangle> triangles;
	private boolean removeBoundaryTriangles = true;

	/*
	 * public Delaunay2() { points = new LinkedList<Point>(); triangles = new
	 * HashSet<Triangle>(); double[] domain = this.defineDomain();
	 * this.initDomain(domain[0], domain[1], domain[2], domain[3]); }
	 */

	public Delaunay2(double xmin, double xmax, double ymin, double ymax) {
		points = new LinkedList<Point>();
		triangles = new HashSet<Triangle>();
		this.initDomain(xmin, xmax, ymin, ymax);
	}

	/*
	 * private double[] defineDomain() { double xmin, xmax, ymin, ymax; xmin =
	 * points.get(0).getX(); ymin = points.get(0).getY(); xmax = xmin; ymax =
	 * ymin; for (int i = 1; i < points.size(); i++) { if (points.get(i).getX()
	 * < xmin) xmin = points.get(i).getX(); if (points.get(i).getX() > xmax)
	 * xmax = points.get(i).getX(); if (points.get(i).getY() < ymin) ymin =
	 * points.get(i).getY(); if (points.get(i).getY() > ymax) ymax =
	 * points.get(i).getY(); } return new double[] { xmin, xmax, ymin, ymax }; }
	 */

	private void initDomain(double xmin, double xmax, double ymin, double ymax) {
		bps = new Point[4];
		bps[0] = new Point(xmin, ymin);
		bps[1] = new Point(xmax, ymin);
		bps[2] = new Point(xmax, ymax);
		bps[3] = new Point(xmin, ymax);

		triangles.add(new Triangle(bps[0], bps[1], bps[2]));
		triangles.add(new Triangle(bps[0], bps[2], bps[3]));
	}

	public void setRemoveBoundaryTriangles(boolean b) {
		removeBoundaryTriangles = b;
	}

	public void addPoint(Point p) {
		points.add(p);
		Set<Triangle> T = getAffectedTriangles(p);
		Set<Edge> B = getBoundaryEdges(T);
		for (Edge b : B)
			triangles.add(new Triangle(p, b.getP1(), b.getP2()));
		for (Triangle t : T)
			triangles.remove(t);
	}

	private Set<Triangle> getAffectedTriangles(Point p) {
		Set<Triangle> T = new HashSet<Triangle>();
		for (Triangle t : triangles) {
			if (t.isInsideCCM(p))
				T.add(t);
		}
		return T;
	}

	private Set<Edge> getBoundaryEdges(Set<Triangle> aff) {
		BoundaryCollector B = new BoundaryCollector();
		for (Triangle t : aff)
			B.addEdges(t.getEdges());
		return B.getBoundaryEdges();
	}

	public List<Point> getPoints() {
		return points;
	}

	public List<Triangle> getTriangles() {
		List<Triangle> T = new LinkedList<Triangle>();
		for (Triangle t : triangles) {
			if (!this.isBoundaryTriangle(t) || !removeBoundaryTriangles)
				T.add(t);
		}
		return T;
	}

	private boolean isBoundaryTriangle(Triangle t) {
		boolean tmp = false;
		for (int i = 0; i < 4; i++)
			tmp |= t.hasPoint(bps[i]);
		return tmp;
	}

}
